<script setup lang="ts">
import type { MapInfo, NpcInfo, MonsterInfo, PlayerInfo } from './type'
import { ref, onMounted, watch } from 'vue'
import { getMapsGetmapinfo } from '@/api/maps/index'
import { isValidJSON, isObject } from '@/utils/tools'
import { XXGame } from './game'

defineOptions({
  name: 'Home',
})

const mapRef = ref<HTMLDivElement>()
const mapInfo = ref<MapInfo>()
const npcInfo = ref<NpcInfo[]>([])
const monsterInfo = ref<MonsterInfo[]>([])
const playerInfo = ref<PlayerInfo[]>([])
const ws = generateWebSocket()

onMounted(async () => {
  await getMapInfo()
  await generateGame()
})

function attack() {
  const params = {
    type: 'attack',
    data: {
      player: playerInfo.value[0].id,
    },
  }
  ws.send(JSON.stringify(params))
}

async function generateGame() {
  const options = {
    container: mapRef.value,
    mapInfo: mapInfo.value,
    npcInfo: npcInfo.value,
    monsterInfo: monsterInfo.value,
    playerInfo: playerInfo.value,
  }
  const game = new XXGame(options)
  await game.init()

  watch(
    () => monsterInfo.value,
    (value, oldValue) => {
      oldValue = oldValue ?? value
      const list = game.monsterContainer.children
      value.forEach((item, index) => {
        const target = list.find((f) => f.label === item.id)
        if (target) {
          const newItem = item
          const oldItem = oldValue[index]
          // 位置变化
          if (!(newItem.x === oldItem.x && newItem.y === oldItem.x)) {
            game.moveContainer(target, oldItem, newItem)
          }
          // 血量变化
          if (newItem.rHp !== oldItem.rHp) {
            game.updateHp(target, newItem.rHp / newItem.hp)
            console.log(oldItem.rHp - newItem.rHp)
            if (newItem.rHp <= 0) {
              target.visible = false
            }
          }
        } else {
          game.generateMonster(item)
        }
      })
    },
    { immediate: true }
  )

  watch(
    () => playerInfo.value,
    (value, oldValue) => {
      oldValue = oldValue ?? value
      const list = game.playerContainer.children
      value.forEach((item, index) => {
        const target = list.find((f) => f.label === item.id)
        if (target) {
          const newItem = item
          const oldItem = oldValue[index]
          // 位置变化
          if (!(newItem.x === oldItem.x && newItem.y === oldItem.x)) {
            game.moveContainer(target, oldItem, newItem)
          }
          // 血量变化
          if (newItem.rHp !== oldItem.rHp) {
            game.updateHp(target, newItem.rHp / newItem.hp)
            console.log(oldItem.rHp - newItem.rHp)
            if (newItem.rHp <= 0) {
              target.visible = false
            }
          }
        } else {
          game.generatePlayer(item)
        }
      })
    },
    { immediate: true }
  )
}

async function getMapInfo() {
  const { data, code } = await getMapsGetmapinfo('000')
  if (code === 200) {
    mapInfo.value = data
    npcInfo.value = data.npc
  }
}

function generateWebSocket() {
  const ws = new WebSocket('ws://127.0.0.1:3001')

  ws.onopen = (e) => {
    console.log('连接服务器成功')
  }

  ws.onclose = (e) => {
    console.log('服务器关闭')
  }

  ws.onerror = (e) => {
    console.log('连接出错')
  }

  // 接受服务器的消息
  ws.onmessage = (e) => {
    const res = isValidJSON(e.data) ? JSON.parse(e.data) : e.data
    if (isObject(res) && res.type === 'monster') {
      monsterInfo.value = res.data
    }
    if (isObject(res) && res.type === 'player') {
      playerInfo.value = res.data
    }
  }

  return ws
}
</script>

<template>
  <div>
    <button @click="attack">攻击</button>
  </div>
  <div ref="mapRef" class="inline-block m-[24px]"></div>
</template>

<style scoped>
button {
  padding: 16px 24px;
  background-color: blue;
  color: #fff;
  margin: 24px;
  margin-bottom: 0;
}
</style>
